ํฅ์๋ ๋ฐ์ดํฐ ํ์นญ, ์ฝ๋ ๋ถํ ๋ฐ ์ํํ ์ฌ์ฉ์ ๊ฒฝํ์ ์ํด React Suspense์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ํ์ฉํ์ธ์. ์ค์ ์์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ํตํด Suspense๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
React Suspense: ๋ฐ์ดํฐ ํ์นญ ๋ฐ ์ฝ๋ ๋ถํ ์ข ํฉ ๊ฐ์ด๋
React Suspense๋ React 16.6์ ๋์ ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ผ๋ก, ๋ฐ์ดํฐ ๋ก๋ฉ์ด๋ ์ฝ๋ ๋ค์ด๋ก๋์ ๊ฐ์ด ๋ฌด์ธ๊ฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์ปดํฌ๋ํธ ๋ ๋๋ง์ "์ผ์ ์ค๋จ"ํ ์ ์๊ฒ ํฉ๋๋ค. ์ด๋ ๋ก๋ฉ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ ๋น๋๊ธฐ ์์ ์ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ์ ์ธ์ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด ๊ฐ์ด๋์์๋ Suspense์ ๊ฐ๋ , ์ฌ์ฉ ์ฌ๋ก ๋ฐ React ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ค์ ์์ ๋ฅผ ์ดํด๋ด ๋๋ค.
React Suspense๋ ๋ฌด์์ธ๊ฐ์?
Suspense๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ๋ React ์ปดํฌ๋ํธ๋ก, ์ปดํฌ๋ํธ๊ฐ Promise๊ฐ ํด๊ฒฐ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋์ฒด UI(์: ๋ก๋ฉ ์คํผ๋)๋ฅผ ํ์ํ ์ ์๊ฒ ํฉ๋๋ค. ์ด Promise๋ ๋ค์๊ณผ ๊ด๋ จ๋ ์ ์์ต๋๋ค:
- ๋ฐ์ดํฐ ํ์นญ: API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ ๊ฒ์ ๊ธฐ๋ค๋ฆฝ๋๋ค.
- ์ฝ๋ ๋ถํ : JavaScript ๋ชจ๋์ด ๋ค์ด๋ก๋๋๊ณ ๊ตฌ๋ฌธ ๋ถ์๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
Suspense ์ด์ ์๋ ๋ก๋ฉ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ข ์ข ๋ณต์กํ ์กฐ๊ฑด๋ถ ๋ ๋๋ง๊ณผ ๋น๋๊ธฐ ์์ ์ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ ํฌํจํ์ต๋๋ค. Suspense๋ ์ ์ธ์ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํ์ฌ ์ด๋ฅผ ๋จ์ํํ๊ณ ์ฝ๋๋ฅผ ๋ ๊น๋ํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
์ฃผ์ ๊ฐ๋
- Suspense ์ปดํฌ๋ํธ:
<Suspense>์ปดํฌ๋ํธ ์์ฒด์ ๋๋ค.fallbackprop์ ๋ฐ์ ๊ฐ์ธ์ง ์ปดํฌ๋ํธ๊ฐ ์ผ์ ์ค๋จ๋๋ ๋์ ํ์ํ UI๋ฅผ ์ง์ ํฉ๋๋ค. - React.lazy(): ์ปดํฌ๋ํธ๋ฅผ ๋์ ์ผ๋ก ๊ฐ์ ธ์ ์ฝ๋ ๋ถํ ์ ๊ฐ๋ฅํ๊ฒ ํ๋ ํจ์์
๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๋ก๋๋ ๋ ํด๊ฒฐ๋๋
Promise๋ฅผ ๋ฐํํฉ๋๋ค. - Promise ํตํฉ: Suspense๋ Promise์ ์ํํ๊ฒ ํตํฉ๋ฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ์์ง ํด๊ฒฐ๋์ง ์์ Promise์์ ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋งํ๋ ค๊ณ ํ๋ฉด "์ผ์ ์ค๋จ"ํ๊ณ ๋์ฒด UI๋ฅผ ํ์ํฉ๋๋ค.
์ฌ์ฉ ์ฌ๋ก
1. Suspense๋ฅผ ์ฌ์ฉํ ๋ฐ์ดํฐ ํ์นญ
Suspense์ ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก ์ค ํ๋๋ ๋ฐ์ดํฐ ํ์นญ ๊ด๋ฆฌ์ ๋๋ค. ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฌ์ฉํ์ฌ ๋ก๋ฉ ์ํ๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ ๋์ Suspense๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ์ ์ธ์ ์ผ๋ก ํ์ํ ์ ์์ต๋๋ค.
์์ : API์์ ์ฌ์ฉ์ ๋ฐ์ดํฐ ํ์นญ
API์์ ํ์น๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ํ์ํ๋ ์ปดํฌ๋ํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. Suspense ์์ด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
import React, { useState, useEffect } from 'react';
function UserProfile() {
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch('https://api.example.com/users/123');
const data = await response.json();
setUser(data);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
if (isLoading) {
return <p>์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ก๋ฉ ์ค...</p>;
}
if (error) {
return <p>์ค๋ฅ: {error.message}</p>;
}
if (!user) {
return <p>์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.</p>;
}
return (
<div>
<h2>{user.name}</h2>
<p>์ด๋ฉ์ผ: {user.email}</p>
</div>
);
}
export default UserProfile;
์ด ์ฝ๋๋ ์๋ํ์ง๋ง ์ฌ๋ฌ ์ํ ๋ณ์(isLoading, error, user)์ ์กฐ๊ฑด๋ถ ๋ ๋๋ง ๋ก์ง์ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค. Suspense๋ฅผ ์ฌ์ฉํ๋ฉด SWR ๋๋ TanStack Query (์ด์ React Query)์ ๊ฐ์ ๋ฐ์ดํฐ ํ์นญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๋จ์ํํ ์ ์์ผ๋ฉฐ, ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ Suspense์ ์ํํ๊ฒ ์๋ํ๋๋ก ์ค๊ณ๋์์ต๋๋ค.
SWR์ Suspense์ ํจ๊ป ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
import React from 'react';
import useSWR from 'swr';
// ๊ฐ๋จํ fetcher ํจ์
const fetcher = (...args) => fetch(...args).then(res => res.json());
function UserProfile() {
const { data: user, error } = useSWR('/api/users/123', fetcher, { suspense: true });
if (error) {
return <p>์ค๋ฅ: {error.message}</p>;
}
return (
<div>
<h2>{user.name}</h2>
<p>์ด๋ฉ์ผ: {user.email}</p>
</div>
);
}
function App() {
return (
<Suspense fallback={<p>์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ก๋ฉ ์ค...</p>}>
<UserProfile />
</Suspense>
);
}
export default App;
์ด ์์ ์์๋:
useSWR์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ํ์นํฉ๋๋ค.suspense: true์ต์ ์ ๋ฐ์ดํฐ๊ฐ ์์ง ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ SWR์ Promise๋ฅผ throwํ๋๋ก ์ง์ํฉ๋๋ค.UserProfile์ปดํฌ๋ํธ๋ ๋ก๋ฉ ๋๋ ์ค๋ฅ ์ํ๋ฅผ ๋ช ์์ ์ผ๋ก ๊ด๋ฆฌํ ํ์๊ฐ ์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉด ๋จ์ํ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋งํฉ๋๋ค.<Suspense>์ปดํฌ๋ํธ๋ SWR์์ throw๋ Promise๋ฅผ catchํ๊ณ ๋ฐ์ดํฐ๊ฐ ํ์น๋๋ ๋์ ๋์ฒด UI(<p>์ฌ์ฉ์ ๋ฐ์ดํฐ ๋ก๋ฉ ์ค...</p>)๋ฅผ ํ์ํฉ๋๋ค.
์ด ์ ๊ทผ ๋ฐฉ์์ ์ปดํฌ๋ํธ ๋ก์ง์ ๋จ์ํํ๊ณ ๋ฐ์ดํฐ ํ์นญ์ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ํฉ๋๋ค.
๋ฐ์ดํฐ ํ์นญ์ ๋ํ ์ ์ญ ๊ณ ๋ ค ์ฌํญ:
์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ๋ ๋ค์์ ๊ณ ๋ คํ์ญ์์ค:
- ๋คํธ์ํฌ ์ง์ฐ ์๊ฐ: ์ง๋ฆฌ์ ์ผ๋ก ๋ค๋ฅธ ์์น์ ์๋ ์ฌ์ฉ์๋ ๋ค์ํ ๋คํธ์ํฌ ์ง์ฐ ์๊ฐ์ ๊ฒฝํํ ์ ์์ต๋๋ค. Suspense๋ ์๊ฒฉ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ํ์นํ๋ ๋์ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ํ์ํ์ฌ ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค. ์ฌ์ฉ์์ ๋ ๊ฐ๊น์ด ๊ณณ์ ๋ฐ์ดํฐ๋ฅผ ์บ์ํ๊ธฐ ์ํด ์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ(CDN)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
- ๋ฐ์ดํฐ ํ์งํ: API๊ฐ ๋ฐ์ดํฐ ํ์งํ๋ฅผ ์ง์ํ๋์ง ํ์ธํ์ฌ ์ฌ์ฉ์์ ์ ํธํ๋ ์ธ์ด์ ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ ์ ์๋๋ก ํฉ๋๋ค.
- API ๊ฐ์ฉ์ฑ: ์ผ๊ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ณด์ฅํ๊ธฐ ์ํด ์ฌ๋ฌ ์ง์ญ์์ API์ ๊ฐ์ฉ์ฑ๊ณผ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํฉ๋๋ค.
2. React.lazy() ๋ฐ Suspense๋ฅผ ์ฌ์ฉํ ์ฝ๋ ๋ถํ
์ฝ๋ ๋ถํ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ ์์ ์ฒญํฌ๋ก ๋ถํ ํ์ฌ ํ์์ ๋ฐ๋ผ ๋ก๋ํ ์ ์๋ ๊ธฐ์ ์ ๋๋ค. ํนํ ํฌ๊ณ ๋ณต์กํ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ํฌ๊ฒ ๊ฐ์ ํ ์ ์์ต๋๋ค.
React๋ ์ปดํฌ๋ํธ ์ฝ๋ ๋ถํ ์ ์ํด React.lazy() ํจ์๋ฅผ ์ ๊ณตํฉ๋๋ค. Suspense์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ค์ด๋ก๋๋๊ณ ๊ตฌ๋ฌธ ๋ถ์๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋์ฒด UI๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
์์ : ์ปดํฌ๋ํธ ์ง์ฐ ๋ก๋ฉ
import React, { Suspense, lazy } from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<p>๋ก๋ฉ ์ค...</p>}>
<OtherComponent />
</Suspense>
</div>
);
}
export default MyComponent;
์ด ์์ ์์๋:
React.lazy()๋ฅผ ์ฌ์ฉํ์ฌOtherComponent๋ฅผ ๋์ ์ผ๋ก ๊ฐ์ ธ์ต๋๋ค. ์ด๋ ์ปดํฌ๋ํธ๊ฐ ๋ก๋๋ ๋ ํด๊ฒฐ๋๋ Promise๋ฅผ ๋ฐํํฉ๋๋ค.<OtherComponent />๋ฅผ<Suspense>๋ก ๊ฐ์ธ๊ณfallbackprop์ ์ ๊ณตํฉ๋๋ค.OtherComponent๊ฐ ๋ก๋๋๋ ๋์ ๋์ฒด UI(<p>๋ก๋ฉ ์ค...</p>)๊ฐ ํ์๋ฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๋ก๋๋๋ฉด ๋์ฒด UI๋ฅผ ๋์ฒดํฉ๋๋ค.
์ฝ๋ ๋ถํ ์ ์ด์ :
- ์ด๊ธฐ ๋ก๋ ์๊ฐ ๊ฐ์ : ์ด๊ธฐ ๋ณด๊ธฐ์ ํ์ํ ์ฝ๋๋ง ๋ก๋ํจ์ผ๋ก์จ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ํธ ์์ฉ ๊ฐ๋ฅํ๊ฒ ๋๋ ๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์ค์ผ ์ ์์ต๋๋ค.
- ๋ฒ๋ค ํฌ๊ธฐ ์ถ์: ์ฝ๋ ๋ถํ ์ JavaScript ๋ฒ๋ค์ ์ ์ฒด ํฌ๊ธฐ๋ฅผ ์ค์ด๋ ๋ฐ ๋์์ด ๋ ์ ์์ผ๋ฉฐ, ์ด๋ ํนํ ์ ๋์ญํญ ์ฐ๊ฒฐ์์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
- ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ: ๋ ๋น ๋ฅธ ์ด๊ธฐ ๋ก๋์ ํ์ํ ๋๋ง ์ฝ๋๋ฅผ ๋ก๋ํจ์ผ๋ก์จ ๋ ์ํํ๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋ค ์ ์์ต๋๋ค.
๊ณ ๊ธ ์ฝ๋ ๋ถํ ๊ธฐ๋ฒ:
- ๊ฒฝ๋ก ๊ธฐ๋ฐ ์ฝ๋ ๋ถํ : ๊ฒฝ๋ก์ ๋ฐ๋ผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ถํ ํ์ฌ ๊ฐ ๊ฒฝ๋ก๊ฐ ํ์ํ ์ฝ๋๋ง ๋ก๋ํ๋๋ก ํฉ๋๋ค. ์ด๋ React Router์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๊ฒ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
- ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์ฝ๋ ๋ถํ : ํนํ ํฌ๊ฑฐ๋ ์์ฃผ ์ฌ์ฉ๋์ง ์๋ ์ปดํฌ๋ํธ์ ๊ฒฝ์ฐ ๊ฐ๋ณ ์ปดํฌ๋ํธ๋ฅผ ๋ณ๋์ ์ฒญํฌ๋ก ๋ถํ ํฉ๋๋ค.
- ๋์ ๊ฐ์ ธ์ค๊ธฐ: ์ฌ์ฉ์ ์ํธ ์์ฉ ๋๋ ๊ธฐํ ์กฐ๊ฑด์ ๋ฐ๋ผ ํ์์ ๋ฐ๋ผ ์ฝ๋๋ฅผ ๋ก๋ํ๊ธฐ ์ํด ์ปดํฌ๋ํธ ๋ด์์ ๋์ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
3. ๋์ ๋ชจ๋ ๋ฐ Suspense
Suspense๋ React์ ๋์ ๋ชจ๋, ์ฆ React๊ฐ ์ฌ๋ฌ ์์ ์ ๋์์ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ๋ ์๋ก์ด ๊ธฐ๋ฅ ์งํฉ์ ํต์ฌ ์์์ ๋๋ค. ๋์ ๋ชจ๋๋ฅผ ์ฌ์ฉํ๋ฉด React๊ฐ ์ค์ํ ์ ๋ฐ์ดํธ์ ์ฐ์ ์์๋ฅผ ์ง์ ํ๊ณ , ์ค๋ ์คํ๋๋ ์์ ์ ์ค๋จํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ต์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
๋์ ๋ชจ๋์ Suspense๋ฅผ ์ฌ์ฉํ๋ฉด React๋ ๋ค์์ ์ํํ ์ ์์ต๋๋ค:
- ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋๊ธฐ ์ ์ ์ปดํฌ๋ํธ ๋ ๋๋ง ์์: React๋ ์ผ๋ถ ๋ฐ์ดํฐ ์ข ์์ฑ์ด ์์ง ํ์น ์ค์ด๋๋ผ๋ ์ปดํฌ๋ํธ ๋ ๋๋ง์ ์์ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด React๋ ๋ถ๋ถ UI๋ฅผ ๋ ์ผ์ฐ ํ์ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ธ์ง๋ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
- ๋ ๋๋ง ์ค๋จ ๋ฐ ์ฌ๊ฐ: React๊ฐ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ ๋์ ์ฐ์ ์์๊ฐ ๋ ๋์ ์ ๋ฐ์ดํธ๊ฐ ๋ค์ด์ค๋ฉด ๋ ๋๋ง ํ๋ก์ธ์ค๋ฅผ ์ค๋จํ๊ณ , ์ฐ์ ์์๊ฐ ๋ ๋์ ์ ๋ฐ์ดํธ๋ฅผ ์ฒ๋ฆฌํ ๋ค์, ๋์ค์ ์ปดํฌ๋ํธ ๋ ๋๋ง์ ์ฌ๊ฐํ ์ ์์ต๋๋ค.
- ๋ฉ์ธ ์ค๋ ๋ ์ฐจ๋จ ๋ฐฉ์ง: ๋์ ๋ชจ๋๋ฅผ ์ฌ์ฉํ๋ฉด React๊ฐ ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ์ค๋ ์คํ๋๋ ์์ ์ ์ํํ ์ ์์ผ๋ฏ๋ก UI๊ฐ ์๋ตํ์ง ์๊ฒ ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
๋์ ๋ชจ๋๋ฅผ ํ์ฑํํ๋ ค๋ฉด React 18์์ createRoot API๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
const root = createRoot(container); // ๋ฃจํธ ์์ฑ
root.render(<App />);
Suspense ์ฌ์ฉ ๋ชจ๋ฒ ์ฌ๋ก
- ๋ฐ์ดํฐ ํ์นญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ: Suspense์ ์ํํ๊ฒ ์๋ํ๋๋ก ์ค๊ณ๋ SWR ๋๋ TanStack Query์ ๊ฐ์ ๋ฐ์ดํฐ ํ์นญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค. ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์บ์ฑ, ์๋ ์ฌ์๋ ๋ฐ ์ค๋ฅ ์ฒ๋ฆฌ์ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ๋ฐ์ดํฐ ํ์นญ ๋ก์ง์ ๋จ์ํํ ์ ์์ต๋๋ค.
- ์๋ฏธ ์๋ ๋์ฒด UI ์ ๊ณต: ๋์ฒด UI๋ ๋ฌด์ธ๊ฐ ๋ก๋ฉ ์ค์์ ๋ช ํํ๊ฒ ๋ํ๋ด์ผ ํฉ๋๋ค. ์คํผ๋, ์งํ๋ฅ ํ์์ค ๋๋ ์ค์ผ๋ ํค ๋ก๋๋ฅผ ์ฌ์ฉํ์ฌ ์๊ฐ์ ์ผ๋ก ๋งค๋ ฅ์ ์ด๊ณ ์ ์ตํ ๋ก๋ฉ ๊ฒฝํ์ ๋ง๋์ญ์์ค.
- ์ค๋ฅ๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌ: ์ค๋ฅ ๊ฒฝ๊ณ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋๋ง ์ค์ ๋ฐ์ํ๋ ์ค๋ฅ๋ฅผ catchํ์ญ์์ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ถฉ๋ํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
- ์ฝ๋ ๋ถํ ์ต์ ํ: ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ์ค์ด๊ธฐ ์ํด ์ ๋ต์ ์ผ๋ก ์ฝ๋ ๋ถํ ์ ์ฌ์ฉํ์ญ์์ค. ํฌ๊ฑฐ๋ ์์ฃผ ์ฌ์ฉ๋์ง ์๋ ์ปดํฌ๋ํธ๋ฅผ ์๋ณํ๊ณ ๋ณ๋์ ์ฒญํฌ๋ก ๋ถํ ํ์ญ์์ค.
- Suspense ๊ตฌํ ํ ์คํธ: Suspense ๊ตฌํ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ก๋ฉ ์ํ์ ์ค๋ฅ๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ๊ธฐ ์ํด ์ฒ ์ ํ ํ ์คํธํ์ญ์์ค.
์ค๋ฅ ๊ฒฝ๊ณ๋ฅผ ์ฌ์ฉํ ์ค๋ฅ ์ฒ๋ฆฌ
Suspense๋ *๋ก๋ฉ* ์ํ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ๋ฉด, ์ค๋ฅ ๊ฒฝ๊ณ๋ ๋ ๋๋ง ์ค *์ค๋ฅ* ์ํ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ค๋ฅ ๊ฒฝ๊ณ๋ ์์ ์ปดํฌ๋ํธ ํธ๋ฆฌ์์ JavaScript ์ค๋ฅ๋ฅผ catchํ๊ณ , ํด๋น ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๊ณ , ์ ์ฒด ์ปดํฌ๋ํธ ํธ๋ฆฌ๊ฐ ์ถฉ๋ํ๋ ๋์ ๋์ฒด UI๋ฅผ ํ์ํ๋ React ์ปดํฌ๋ํธ์ ๋๋ค.
๋ค์์ ์ค๋ฅ ๊ฒฝ๊ณ์ ๊ธฐ๋ณธ ์์ ๋๋ค:
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// ๋ค์ ๋ ๋๋ง์์ ๋์ฒด UI๋ฅผ ํ์ํ๋๋ก ์ํ ์
๋ฐ์ดํธ
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// ์ค๋ฅ ๋ณด๊ณ ์๋น์ค์ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ ์๋ ์์ต๋๋ค.
console.error(error, errorInfo);
}
render() {
if (this.state.hasError) {
// ์ฌ์ฉ์ ์ ์ ๋์ฒด UI๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค.
return <h1>๋ฌด์ธ๊ฐ ์๋ชป๋์์ต๋๋ค.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
์ค๋ฅ ๊ฒฝ๊ณ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ค๋ฅ๋ฅผ ๋ฐ์์ํฌ ์ ์๋ ์ปดํฌ๋ํธ ์ฃผ์์ ๋ํํ์ญ์์ค:
import ErrorBoundary from './ErrorBoundary';
import MyComponent from './MyComponent';
function App() {
return (
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
);
}
export default App;
Suspense์ ์ค๋ฅ ๊ฒฝ๊ณ๋ฅผ ๊ฒฐํฉํ๋ฉด ๋ก๋ฉ ์ํ์ ์ค๋ฅ๋ฅผ ๋ชจ๋ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๋ ๊ฐ๋ ฅํ๊ณ ํ๋ ฅ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์์ต๋๋ค.
์ค์ ์ฌ๋ก
๋ค์์ Suspense๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ ์ ์๋ ๋ช ๊ฐ์ง ์ค์ ์ฌ๋ก์ ๋๋ค:
- ์ ์ ์๊ฑฐ๋ ์น์ฌ์ดํธ: Suspense๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ ์ธ๋ถ ์ ๋ณด ๋๋ ์ด๋ฏธ์ง๋ฅผ ํ์นํ๋ ๋์ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ํ์ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ ๋ก๋๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋น ํ์ด์ง๋ฅผ ๋ณด๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
- ์์ ๋ฏธ๋์ด ํ๋ซํผ: ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ฅผ ์๋๋ก ์คํฌ๋กคํจ์ ๋ฐ๋ผ ๋๊ธ ๋๋ ๊ฒ์๋ฌผ์ ์ง์ฐ ๋ก๋ํ๊ธฐ ์ํด Suspense๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ์ด์ง์ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ด ๊ฐ์ ๋๊ณ ๋ค์ด๋ก๋ํด์ผ ํ๋ ๋ฐ์ดํฐ ์์ด ์ค์ด๋ค ์ ์์ต๋๋ค.
- ๋์๋ณด๋ ์ ํ๋ฆฌ์ผ์ด์ : ์ฐจํธ ๋๋ ๊ทธ๋ํ ๋ฐ์ดํฐ๋ฅผ ํ์นํ๋ ๋์ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ํ์ํ๊ธฐ ์ํด Suspense๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ ์ํํ๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์์ : ๊ตญ์ ์ ์ ์๊ฑฐ๋ ํ๋ซํผ
์ ์ธ๊ณ์ ์ผ๋ก ์ ํ์ ํ๋งคํ๋ ๊ตญ์ ์ ์ ์๊ฑฐ๋ ํ๋ซํผ์ ๊ณ ๋ คํ์ญ์์ค. ํ๋ซํผ์ Suspense์ React.lazy()๋ฅผ ํ์ฉํ์ฌ ๋ค์์ ์ํํ ์ ์์ต๋๋ค:
- ์ ํ ์ด๋ฏธ์ง ์ง์ฐ ๋ก๋:
React.lazy()๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ์ ํ์๋ ๋๋ง ๋ก๋ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ํ ๋ชฉ๋ก ํ์ด์ง์ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ํฌ๊ฒ ๋จ์ถํ ์ ์์ต๋๋ค. ์ค์ ์ด๋ฏธ์ง๊ฐ ๋ก๋๋๋ ๋์ ํ๋ ์ด์คํ๋ ์ด๋ฏธ์ง๋ฅผ ํ์ํ๊ธฐ ์ํด ๊ฐ ์ง์ฐ ๋ก๋๋ ์ด๋ฏธ์ง๋ฅผ<Suspense fallback={<img src="placeholder.png" alt="๋ก๋ฉ ์ค..." />}>๋ก ๊ฐ์๋๋ค. - ๊ตญ๊ฐ๋ณ ์ปดํฌ๋ํธ ์ฝ๋ ๋ถํ : ํ๋ซํผ์ ๊ตญ๊ฐ๋ณ ์ปดํฌ๋ํธ(์: ํตํ ํ์, ์ฃผ์ ์
๋ ฅ ํ๋)๊ฐ ์๋ ๊ฒฝ์ฐ
React.lazy()๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ํน์ ๊ตญ๊ฐ๋ฅผ ์ ํํ ๋๋ง ์ด๋ฌํ ์ปดํฌ๋ํธ๋ฅผ ๋ก๋ํฉ๋๋ค. - ํ์งํ๋ ์ ํ ์ค๋ช ํ์น: Suspense๋ฅผ ์ฌ์ฉํ๋ SWR๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ํ์นญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ์ ํธํ๋ ์ธ์ด๋ก ์ ํ ์ค๋ช ์ ํ์นํฉ๋๋ค. ํ์งํ๋ ์ค๋ช ์ด ํ์น๋๋ ๋์ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ํ์ํฉ๋๋ค.
๊ฒฐ๋ก
React Suspense๋ React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ์ ๊ฒฝํ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋๋ค. ๋ก๋ฉ ์ํ ๋ฐ ์ฝ๋ ๋ถํ ์ ๊ด๋ฆฌํ๋ ์ ์ธ์ ๋ฐฉ๋ฒ์ ์ ๊ณตํจ์ผ๋ก์จ Suspense๋ ์ฝ๋๋ฅผ ๋จ์ํํ๊ณ ๋น๋๊ธฐ ์์ ์ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ํฉ๋๋ค. ์๊ท๋ชจ ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ๊ตฌ์ถํ๋ ๋๊ท๋ชจ ๊ธฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ Suspense๋ ๋ ์ํํ๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋๋ฉฐ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
Suspense๋ฅผ ๋ฐ์ดํฐ ํ์นญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ ์ฝ๋ ๋ถํ ๊ธฐ์ ๊ณผ ํตํฉํจ์ผ๋ก์จ React์ ๋์ ๋ชจ๋์ ์ ์ฒด ์ ์ฌ๋ ฅ์ ํ์ฉํ๊ณ ์ง์ ์ผ๋ก ํ๋์ ์ด๊ณ ๋งค๋ ฅ์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์์ต๋๋ค. Suspense๋ฅผ ์์ฉํ๊ณ React ๊ฐ๋ฐ์ ๋ค์ ๋จ๊ณ๋ก ๋์ด์ฌ๋ฆฌ์ญ์์ค.